/*!
 Temelia - Iterator implementation source file.

 Copyright (C) 2008, 2009 Ceata (http://ceata.org/proiecte/temelia).

 @author Dascalu Laurentiu, Macovei Alexandru

 This program is free software; you can redistribute it and
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 3
 of the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include <stdlib.h>
#include "include/iterator.h"
#include "include/common.h"

struct _linked_list_iterator_t
{
	/*! user's key */
	void *key;

	/*! reference to the next node */
	struct _linked_list_iterator_t *next;
};

struct _doubly_linked_list_iterator_t
{
	/*! user's key */
	void *key;

	/*! reference to the next node */
	struct _doubly_linked_list_iterator_t *next;

	/*! reference to the previous node */
	struct _doubly_linked_list_iterator_t *prev;
};

linked_list_iterator_t linked_list_iterator_new(void *default_key,
		linked_list_iterator_t default_next)
{
	linked_list_iterator_t it;

	it = (linked_list_iterator_t) _new(sizeof(struct _linked_list_iterator_t));

	_ASSERT(it, ==, NULL, NULL_POINTER, NULL);

	it->key = default_key;
	it->next = default_next;

	return it;
}
void linked_list_iterator_delete(linked_list_iterator_t it)
{
	_delete(it);
}

void *linked_list_iterator_get_key(linked_list_iterator_t it)
{
	_ASSERT(it, ==, NULL, NULL_POINTER, NULL);

	return it->key;
}

linked_list_iterator_t linked_list_iterator_get_next(linked_list_iterator_t it)
{
	_ASSERT(it, ==, NULL, NULL_POINTER, NULL);

	return it->next;
}

void linked_list_iterator_set_key(linked_list_iterator_t it, void *new_key)
{
	_ASSERT(it, ==, NULL, NULL_POINTER,);

	it->key = new_key;
}

void linked_list_iterator_set_next(linked_list_iterator_t it,
		linked_list_iterator_t new_next)
{
	_ASSERT(it, ==, NULL, NULL_POINTER,);

	it->next = new_next;
}

void linked_list_iterator_join(linked_list_iterator_t left,
		linked_list_iterator_t middle, linked_list_iterator_t right)
{
	if (left)
		left->next = middle;
	if (middle)
		middle->next = right;
}

void linked_list_iterator_split(linked_list_iterator_t left,
		linked_list_iterator_t middle, linked_list_iterator_t right)
{
	if (left)
		left->next = NULL;
	if (right)
		middle->next = NULL;
}

doubly_linked_list_iterator_t doubly_linked_list_iterator_new(void *key,
		doubly_linked_list_iterator_t default_prev,
		doubly_linked_list_iterator_t default_next)
{
	doubly_linked_list_iterator_t it;

	it = _new(sizeof(struct _doubly_linked_list_iterator_t));

	_ASSERT(it, ==, NULL, NULL_POINTER, NULL);

	it->key = key;
	it->prev = default_prev;
	it->next = default_next;

	return it;
}

void doubly_linked_list_iterator_delete(doubly_linked_list_iterator_t it)
{
	_delete(it);
}

void *doubly_linked_list_iterator_get_key(doubly_linked_list_iterator_t it)
{
	_ASSERT(it, ==, NULL, NULL_POINTER, NULL);

	return it->key;
}

doubly_linked_list_iterator_t doubly_linked_list_iterator_get_prev(
		doubly_linked_list_iterator_t it)
{
	_ASSERT(it, ==, NULL, NULL_POINTER, NULL);

	return it->prev;
}

doubly_linked_list_iterator_t doubly_linked_list_iterator_get_next(
		doubly_linked_list_iterator_t it)
{
	_ASSERT(it, ==, NULL, NULL_POINTER, NULL);

	return it->next;
}

void doubly_linked_list_iterator_set_key(doubly_linked_list_iterator_t it,
		void *key)
{
	_ASSERT(it, ==, NULL, NULL_POINTER,);

	it->key = key;
}

void doubly_linked_list_iterator_set_prev(doubly_linked_list_iterator_t it,
		doubly_linked_list_iterator_t prev)
{
	_ASSERT(it, ==, NULL, NULL_POINTER,);

	it->prev = prev;
}

void doubly_linked_list_iterator_set_next(doubly_linked_list_iterator_t it,
		doubly_linked_list_iterator_t next)
{
	_ASSERT(it, ==, NULL, NULL_POINTER,);

	it->next = next;
}

void doubly_linked_list_iterator_join(doubly_linked_list_iterator_t left,
		doubly_linked_list_iterator_t middle,
		doubly_linked_list_iterator_t right)
{
	if (left)
		left->next = middle;
	if (middle)
	{
		middle->prev = left;
		middle->next = right;
	}
	if (right)
		right->prev = middle;
}

void doubly_linked_list_iterator_spit(doubly_linked_list_iterator_t left,
		doubly_linked_list_iterator_t middle,
		doubly_linked_list_iterator_t right)
{
	if (left)
		left->next = NULL;
	if (middle)
		middle->prev = middle->next = NULL;
	if (right)
		right->prev = NULL;
}
